/**
 * create by zhangpu
 * date:2015年3月2日
 */
package com.acooly.module.openapi.client.provider.wft;

import com.acooly.core.utils.Strings;
import com.acooly.module.openapi.client.api.AbstractApiServiceClient;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.exception.ApiServerException;
import com.acooly.module.openapi.client.api.marshal.ApiMarshal;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.transport.Transport;
import com.acooly.module.openapi.client.provider.wft.domain.WftNotify;
import com.acooly.module.openapi.client.provider.wft.domain.WftRequest;
import com.acooly.module.openapi.client.provider.wft.domain.WftResponse;
import com.acooly.module.openapi.client.provider.wft.marshall.*;
import com.acooly.module.openapi.client.provider.wft.message.WftBillDownloadRequest;
import com.acooly.module.openapi.client.provider.wft.message.WftBillDownloadResponse;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;

/**
 * ApiService执行器
 *
 * @author zhangpu
 */
@Component("wftApiServiceClient")
@Slf4j
public class WftApiServiceClient
        extends AbstractApiServiceClient<WftRequest, WftResponse, WftNotify, WftNotify> {


    public static final String PROVIDER_NAME = "wft";

    @Resource(name = "wftHttpTransport")
    private Transport transport;

    @Resource(name = "wftRequestMarshall")
    private WftRequestMarshall requestMarshal;

    @Resource(name = "wftRedirectMarshall")
    private WftRedirectMarshall redirectMarshal;

    @Resource(name = "wftSignMarshall")
    private WftSignMarshall signMarshall;

    @Autowired
    private WftResponseUnmarshall responseUnmarshal;
    @Autowired
    private WftNotifyUnmarshall notifyUnmarshal;

    @Autowired
    private OpenAPIClientWftProperties openAPIClientWftProperties;

    @Override
    public WftResponse execute(WftRequest request) {
        try {
            beforeExecute(request);
            if (Strings.isBlank(request.getGatewayUrl())) {
                request.setGatewayUrl(openAPIClientWftProperties.getGatewayUrl());
            }
            if(Strings.isBlank(request.getMchId())) {
                request.setMchId(openAPIClientWftProperties.getPartnerId());
            }
            String url = request.getGatewayUrl();
            String requestMessage = getRequestMarshal().marshal(request);
            log.info("请求报文: {}", requestMessage);
            String responseMessage = getTransport().exchange(requestMessage, url);
            WftResponse t = getResponseUnmarshal().unmarshal(responseMessage, request.getService());
            t.setService(request.getService());
            afterExecute(t);
            return t;
        } catch (ApiServerException ose) {
            log.error("服务器:" + ose.getMessage(), ose);
            throw ose;
        } catch (ApiClientException oce) {
            log.error("客户端:" + oce.getMessage(), oce);
            throw oce;
        } catch (Exception e) {
            log.error("内部错误:" + e.getMessage(), e);
            throw new ApiClientException("内部错误:" + e.getMessage());
        }
    }

    public WftBillDownloadResponse billDownload(WftRequest request) {
        WftBillDownloadResponse response = new WftBillDownloadResponse();
        String status = "1";
        String resultCode = "1";
        OutputStream outputStream = null;
        try {
            beforeExecute(request);
            WftBillDownloadRequest billDownloadRequest = (WftBillDownloadRequest) request;
            if (Strings.isBlank(request.getGatewayUrl())) {
                request.setGatewayUrl(openAPIClientWftProperties.getDownLoadUrl());
            }
            if(Strings.isBlank(request.getMchId())) {
                request.setMchId(openAPIClientWftProperties.getPartnerId());
            }
            String url = request.getGatewayUrl();
            String requestMessage = getRequestMarshal().marshal(request);
            log.info("请求报文: {}", requestMessage);
            String responseMessage = getTransport().exchange(requestMessage, url);
            try {
                JSON.parseObject(responseMessage);
                response.setErrMsg("对账文件下载失败");
                response.setMessage(responseMessage);
            }catch (Exception e) {
                String filePath = billDownloadRequest.getFilePath();
                if (Strings.isBlank(filePath)) {
                    filePath = openAPIClientWftProperties.getFilePath();
                }
                String fileName = billDownloadRequest.getFileName();
                String fileSuffix = billDownloadRequest.getFileSuffix();
                if (Strings.isBlank(fileName)) {
                    fileName = billDownloadRequest.getBillDate() + "." + fileSuffix;
                } else {
                    fileName = fileName + "." + fileSuffix;
                }
                File billFile = new File(filePath + File.separator + fileName);
                if (!billFile.exists()) {
                    billFile.getParentFile().mkdirs();
                }
                billFile.createNewFile();
                outputStream = new FileOutputStream(billFile);
                outputStream.write(responseMessage.getBytes());
                outputStream.flush();
                status = "0" ;
                resultCode = "0" ;
            }
            log.info("账期billDate={}对账文件下载完毕", billDownloadRequest.getBillDate());
        } catch (ApiServerException ose) {
            log.error("服务器:" + ose.getMessage(), ose);
            throw ose;
        } catch (ApiClientException oce) {
            log.error("客户端:" + oce.getMessage(), oce);
            throw oce;
        } catch (Exception e) {
            log.error("内部错误:" + e.getMessage(), e);
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                log.info("输出流关闭失败:{}", e.getMessage());
            }
            response.setStatus(status);
            response.setResultCode(resultCode);
        }
        return response;
    }

    public WftNotify notice(HttpServletRequest request, String serviceKey) {
        try {
            Map<String, String> notifyData = getSignMarshall().getDateMap(request);
            WftNotify notify = getNoticeUnmarshal().unmarshal(notifyData, serviceKey);
            afterNotice(notify);
            return notify;
        } catch (ApiClientException oce) {
            log.warn("客户端:{}", oce.getMessage());
            throw oce;
        } catch (Exception e) {
            log.warn("内部错误:{}", e.getMessage());
            throw new ApiClientException("内部错误:" + e.getMessage());
        }
    }

    @Override
    protected ApiMarshal<String, WftRequest> getRequestMarshal() {
        return this.requestMarshal;
    }

    @Override
    protected ApiUnmarshal<WftResponse, String> getResponseUnmarshal() {
        return this.responseUnmarshal;
    }

    @Override
    protected ApiUnmarshal<WftNotify, Map<String, String>> getNoticeUnmarshal() {
        return this.notifyUnmarshal;
    }

    @Override
    protected ApiMarshal<String, WftRequest> getRedirectMarshal() {
        return this.redirectMarshal;
    }

    @Override
    protected Transport getTransport() {
        return this.transport;
    }

    @Override
    protected ApiUnmarshal<WftNotify, Map<String, String>> getReturnUnmarshal() {
        return this.notifyUnmarshal;
    }

    public WftSignMarshall getSignMarshall() {
        return signMarshall;
    }

    public void setSignMarshall(WftSignMarshall signMarshall) {
        this.signMarshall = signMarshall;
    }

    @Override
    public String getName() {
        return PROVIDER_NAME;
    }
}
